---@class Battle.Buffer:Battle.BuffBase
---@field New fun():Battle.Buffer
local Buffer = Battle.CreateClass("Buffer",Battle.BuffBase)
Battle.Buffer = Buffer

function Buffer:OnCreate()
    Battle.BuffBase.OnCreate(self)
    self.cfg = nil
    self.activeCount = 0 --激活次数
    self.stateList = {}
    self.offSet = Vector3.New()
    self.pos =  Vector3.New()
    self.resName = ""
    self.LoadRequestId = 0
    self.maxOverlay = 1;
    self.buffScript = nil;
    self.buffEffectType = 0
    self.specialStateList = {}  --特殊效果
    self.addedSpecialStateList = {} --已添加的特殊效果
    self.signList = {}      --标记位
    self.mutexList = {}  --互斥

    self.isDestroyed = false
    self.isDie = false
    self.isLoading = false
    self.isCreate = true
end

function Buffer:OnDestroy()
    if self.buffScript then
        self.buffScript:OnDestroy()
    end
    self.isDestroyed = true
    self.LoadRequestId = 0
    self.isDie = true
    self.offSet = nil
    self.pos = nil

end
function Buffer:Set(buffId,overlay,targetId,during,sourceSender,sourceSkillId,sourceBuffId)
    Battle.BuffBase.Set(self,buffId,overlay,targetId,during,sourceSender,sourceSkillId,sourceBuffId)
    self.cfg = DataTable.GetById("t_buff",buffId)
    if not self.cfg then
        logError("找不到t_buff "..buffId)
        return
    end
    self.buffEffectType = self.cfg.f_Effect
    self.maxOverlay = self.cfg.f_Number
    self:ParseCondition()
    if not string.IsEmpty(self.cfg.f_SpecialBuff) then
        local param = decodeJsonStrToTable(self.cfg.f_SpecialBuff)
        for k,v in pairs(param) do
            self.specialStateList[v] = true
        end
    end
    if not string.IsEmpty(self.cfg.f_Sign) then
        local param = decodeJsonStrToTable(self.cfg.f_Sign)
        for k,v in pairs(param) do
            self.signList[v] = true
        end
    end
    if not string.IsEmpty(self.cfg.f_Mutex) then
        local param = decodeJsonStrToTable(self.cfg.f_Mutex)
        for k,v in pairs(param) do
            self.mutexList[v] = true
        end
    end
    local buffTime = self.cfg.f_ContinuedTime;
    if during == nil then
        if buffTime == 0 then
            self.during = -1
        else
            self.during = buffTime/1000
        end
    end
    if self.during > 0  then
        self.isInDuring = true
    end
    if self.isCreate then
        self:AddSpecialState()
        self:AddSign()
    end
    self.isCreate = false
    local actor = Battle.ActorManager.GetActor(targetId)
    if actor then
        actor.eventSystem:FireEvent(Battle.Event.BuffCreate,Battle.EventArgs.BufferArgs:Create(sourceSender,self))
    end
    --self:OnBuffStart()
    --self:LoadModel()
end
function Buffer:ParseCondition()
    self.activeFirstConditionType = self.cfg.f_TriggerOpportunity
    ---@type Battle.IBuffCondition[]
    self.activeSecondConditionList = {}
    if not string.IsEmpty(self.cfg.f_TriggerCondition) then
        local param = decodeJsonStrToTable(self.cfg.f_TriggerCondition)
        for k,v in pairs(param) do
            local type = v[1]
            local value = v[2]
            if type == Battle.TriggerCondition.Probability then
                table.insert(self.activeSecondConditionList,Battle.BuffProbabilityCondition.New(self,value))
            elseif type == Battle.TriggerCondition.EnergyGreater then
                local actor = Battle.ActorManager.GetActor(self.targetId)
                table.insert(self.activeSecondConditionList,Battle.BuffHeroEnergyCondition.New(self,value,actor.camp))
            elseif type == Battle.TriggerCondition.CarryMark then
                table.insert(self.activeSecondConditionList,Battle.BuffCarryMarkCondition.New(self,value))
            elseif type == Battle.TriggerCondition.TargetHide then
                table.insert(self.activeSecondConditionList,Battle.BuffTargetHideCondition.New(self))
            elseif type == Battle.TriggerCondition.TimeInterval then
                table.insert(self.activeSecondConditionList,Battle.BuffTimeIntervalCondition.New(self,value))
            elseif type == Battle.TriggerCondition.SelfHpLowPer then
                table.insert(self.activeSecondConditionList,Battle.BuffHPLowCondition.New(self,value))
            elseif type == Battle.TriggerCondition.ActiveCountLimit then
                table.insert(self.activeSecondConditionList,Battle.BuffLimitCountCondition.New(self,value))
            end
        end
    end
end
function Buffer:CheckSecondCondition(param)
    for k,v in pairs(self.activeSecondConditionList) do
        v:SetConditionData(param)
        if not v:Check() then return false end
    end
    return true
end
function Buffer:SecondConditionExecute()
    for k,v in pairs(self.activeSecondConditionList) do
       v:Execute()
    end
end
function Buffer:HasSign(signType)
    return self.signList[signType]
end
function Buffer:GetSign()
    for k,v in pairs(self.signList) do
        return k
    end
    return 0
end
function Buffer:HasMutex(mutex)
    return self.mutexList[mutex]
end
function Buffer:AddSpecialState()
    local target = self:GetTarget()
    if target == nil then return end
    if target.effectStateSystem:HasState(Battle.FighterStateEnum.IMMUNITY_CTRL) and self:HasSign(Battle.BuffSignType.Ctrl) then
        return
    end
    for k,v in pairs(self.specialStateList) do
        self.addedSpecialStateList[k] = true
        target.effectStateSystem:AddState(k)
    end
end
function Buffer:RemoveSpecialState()
    local target = self:GetTarget()
    if target == nil then return end
    for k,v in pairs(self.addedSpecialStateList) do
        target.effectStateSystem:RemoveState(k)
    end
end
function Buffer:AddSign()
    local target = self:GetTarget()
    if target == nil then return end
    for k,v in pairs(self.signList) do
        target.signSystem:AddSign(k)
    end
end
function Buffer:RemoveSign()
    local target = self:GetTarget()
    if target == nil then return end
    for k,v in pairs(self.signList) do
        target.signSystem:RemoveSign(k)
    end
end
---@return Battle.Entity
function Buffer:GetTarget()
    return Battle.ActorManager.GetActor(self.targetId)
end

function Buffer:IsDie()
    return self.isDie
end
function Buffer:TimeEnd()
    self.isDie = true
end

function Buffer:Update(dt)
    Battle.BuffBase.Update(self,dt)
    for k,v in pairs(self.activeSecondConditionList) do
        v:Update(dt)
    end
    Battle.EventManager.notifyEventListener(Battle.BuffTriggerType.FRAME, self.targetId)
    if self.buffScript then
        --如果存在buff脚本则buff脚本触发
        self.buffScript:Update(dt);
    end

end

---实例化后，生效前调用(还未加入buff容器中)
function Buffer:OnBuffAwake()
    if self.buffScript then
        self.buffScript.OnBuffAwake();
    end
end
---buff生效时
function Buffer:OnBuffStart(...)
    Battle.BuffBase.OnBuffStart(self)
    if self.buffScript then
        --如果存在buff脚本则buff脚本触发
        self.buffScript:OnBuffStart(...);
    end
    self.activeCount = self.activeCount + 1
    local actor = Battle.ActorManager.GetActor(self.targetId)
    if actor then
        actor.eventSystem:FireEvent(Battle.Event.BuffActive,Battle.EventArgs.BufferArgs:Create(actor,self))
    end
end
---相同类型时刷新(更新buff层数、等级、持续时间等)
function Buffer:OnBuffRefresh(overlay)
    local old = self.overlay
    self.overlay = overlay
    self.curTime = 0
    if self.buffScript then
        self.buffScript:OnBuffRefresh(overlay,old)
    end
    local actor = Battle.ActorManager.GetActor(self.targetId)
    if actor then
        actor.eventSystem:FireEvent(Battle.Event.BuffLayerChange,Battle.EventArgs.BufferArgs:Create(actor,self))
    end
end
---当buff销毁前(还未从buff容器中移除)
function Buffer:OnBuffRemove()
    if self.isDie then
        return
    end
    self.isDie = true
    self:RemoveSpecialState()
    self:RemoveSign()
    if self.buffScript then
        self.buffScript:OnBuffRemove()
    end
    --Battle.BufferMgr.RemoveBuff(self.targetId, self.buffId)
    local actor = Battle.ActorManager.GetActor(self.targetId)
    if actor then
        actor.eventSystem:FireEvent(Battle.Event.BuffDestroy,Battle.EventArgs.BufferArgs:Create(actor,self))
    end
end
